/*
 * flash_example.c
 * STM32F446 FLASH驱动使用示例
 * 注意：在实际应用中，应避免频繁擦除和写入FLASH以延长其使用寿命
 */

#include "flash_driver.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// ADS1230数据示例
#define ADS1230_ZERO_DATA_DEFAULT      0xFFFC1700  // 默认零位数据
#define ADS1230_CALIB_FACTOR_DEFAULT   1.0f        // 默认校准因子

// 定义示例用的FLASH扇区和地址
// 注意：避免使用包含程序代码的扇区，这里使用扇区5作为示例
#define EXAMPLE_SECTOR      FLASH_SECTOR_5  // 使用扇区5进行示例
#define EXAMPLE_ADDRESS     0x08020000      // 扇区5的起始地址

// 测试数据大小
#define TEST_DATA_SIZE      256             // 256字节（确保在单个扇区内）

/**
 * @brief 打印FLASH操作结果
 * @param result 操作结果代码
 * @param operation 操作名称
 */
void PrintFlashResult(uint8_t result, const char* operation)
{
    switch (result)
    {
        case FLASH_OK:
            printf("✅ %s: 成功\n", operation);
            break;
        case FLASH_ERROR:
            printf("❌ %s: 错误\n", operation);
            break;
        case FLASH_BUSY:
            printf("⚠️  %s: FLASH忙\n", operation);
            break;
        case FLASH_TIMEOUT:
            printf("⏱️ %s: 超时\n", operation);
            break;
        case FLASH_ADDR_ERROR:
            printf("❌ %s: 地址错误\n", operation);
            break;
        case FLASH_LENGTH_ERROR:
            printf("❌ %s: 长度错误，跨扇区操作\n", operation);
            break;
        default:
            printf("❓ %s: 未知结果 (0x%02X)\n", operation, result);
            break;
    }
}

/**
 * @brief 执行简单的FLASH读写测试
 * @param address 测试起始地址
 * @param test_size 测试数据大小
 * @return true 测试成功, false 测试失败
 */
bool FLASH_SimpleTest(uint32_t address, uint32_t test_size)
{
    uint8_t *write_buffer = NULL;
    uint8_t *read_buffer = NULL;
    uint8_t result = 0;
    uint32_t i = 0;
    bool verify_ok = true;
    uint32_t sector = FLASH_GetSectorByAddress(address);
    
    // 检查地址是否有效
    if (sector > FLASH_SECTOR_7)
    {
        printf("❌ 无效的FLASH地址: 0x%08X\n", address);
        return false;
    }
    
    // 动态分配缓冲区
    write_buffer = (uint8_t *)malloc(test_size);
    read_buffer = (uint8_t *)malloc(test_size);
    
    if ((write_buffer == NULL) || (read_buffer == NULL))
    {
        printf("❌ 内存分配失败\n");
        if (write_buffer != NULL) free(write_buffer);
        if (read_buffer != NULL) free(read_buffer);
        return false;
    }
    
    // 初始化测试数据
    printf("📝 初始化测试数据...\n");
    for (i = 0; i < test_size; i++)
    {
        write_buffer[i] = (uint8_t)(i & 0xFF);  // 填充测试数据
    }
    
    // 初始化FLASH
    printf("🔧 初始化FLASH...\n");
    result = FLASH_Init();
    PrintFlashResult(result, "FLASH初始化");
    if (result != FLASH_OK) goto cleanup;
    
    // 检查地址和长度是否在单个扇区内
    printf("📋 检查地址和长度是否在单个扇区内...\n");
    result = FLASH_CheckSingleSector(address, test_size);
    PrintFlashResult(result, "单扇区检查");
    if (result != FLASH_OK) goto cleanup;
    
    // 擦除扇区
    printf("🧹 擦除扇区 %d...\n", sector);
    printf("⚠️  警告：此操作将清除该扇区的所有数据！\n");
    result = FLASH_EraseSector(sector);
    PrintFlashResult(result, "扇区擦除");
    if (result != FLASH_OK) goto cleanup;
    
    // 写入数据
    printf("💾 写入FLASH数据 (地址: 0x%08X, 长度: %d字节)...\n", 
           address, test_size);
    result = FLASH_Write(address, write_buffer, test_size);
    PrintFlashResult(result, "FLASH写入");
    if (result != FLASH_OK) goto cleanup;
    
    // 读取数据
    printf("📖 从FLASH读取数据...\n");
    result = FLASH_Read(address, read_buffer, test_size);
    PrintFlashResult(result, "FLASH读取");
    if (result != FLASH_OK) goto cleanup;
    
    // 验证数据
    printf("🔍 验证数据...\n");
    for (i = 0; i < test_size; i++)
    {
        if (read_buffer[i] != write_buffer[i])
        {
            verify_ok = false;
            printf("❌ 数据验证失败: 地址偏移 0x%04X, 期望: 0x%02X, 实际: 0x%02X\n",
                   i, write_buffer[i], read_buffer[i]);
            break;
        }
        
        // 每验证32字节打印一次进度
        if (((i + 1) % 32 == 0) || (i + 1 == test_size))
        {
            printf("✅ 已验证 %lu/%lu 字节\r", i + 1, test_size);
        }
    }
    printf("\n");
    
    if (verify_ok)
    {
        printf("✅ 数据验证成功！\n");
    }
    else
    {
        printf("❌ 数据验证失败！\n");
    }
    
cleanup:
    // 释放动态分配的内存
    if (write_buffer != NULL) free(write_buffer);
    if (read_buffer != NULL) free(read_buffer);
    
    return verify_ok && (result == FLASH_OK);
}

/**
 * @brief FLASH驱动测试函数
 */
void FLASH_Test(void)
{
    printf("\n======================================================\n");
    printf("          STM32F446 FLASH 驱动测试程序          \n");
    printf("======================================================\n\n");
    
    // 打印扇区信息
    printf("📊 扇区信息:\n");
    printf("扇区 %d 起始地址: 0x%08X\n", 
           EXAMPLE_SECTOR, FLASH_GetSectorStartAddress(EXAMPLE_SECTOR));
    printf("扇区 %d 大小: %d 字节\n", 
           EXAMPLE_SECTOR, FLASH_GetSectorSize(EXAMPLE_SECTOR));
    printf("地址 0x%08X 所在扇区: %d\n\n", 
           EXAMPLE_ADDRESS, FLASH_GetSectorByAddress(EXAMPLE_ADDRESS));
    
    // 执行简单的读写测试
    printf("🔄 开始执行FLASH读写测试...\n");
    if (FLASH_SimpleTest(EXAMPLE_ADDRESS, TEST_DATA_SIZE))
    {
        printf("🎉 FLASH测试全部通过！\n");
    }
    else
    {
        printf("💥 FLASH测试失败！\n");
    }
    
    printf("\n======================================================\n");
    printf("                  测试完成                   \n");
    printf("======================================================\n");
}

/**
 * @brief ADS1230数据FLASH读写测试
 * @return 操作状态
 */
uint8_t ADS1230_FlashTest(void)
{
    uint8_t status = FLASH_OK;
    int32_t write_zero_data = ADS1230_ZERO_DATA_DEFAULT;
    int32_t read_zero_data = 0;
    float write_calib_factor = ADS1230_CALIB_FACTOR_DEFAULT;
    float read_calib_factor = 0.0f;
    
    printf("\n=== ADS1230 FLASH数据测试 ===\n");
    
    // 初始化FLASH
    printf("初始化FLASH...");
    if (FLASH_Init() != FLASH_OK)
    {
        printf("失败！\n");
        return FLASH_ERROR;
    }
    printf("成功\n");
    
    // 写入ADS1230数据
    printf("写入ADS1230数据...\n");
    printf("  零位数据: 0x%08X\n", write_zero_data);
    printf("  校准因子: %.6f\n", write_calib_factor);
    
    status = FLASH_WriteADS1230Data(write_zero_data, write_calib_factor);
    if (status != FLASH_OK)
    {
        printf("写入失败！错误码: %d\n", status);
        return status;
    }
    printf("写入成功\n");
    
    // 读取ADS1230数据
    printf("\n读取ADS1230数据...");
    status = FLASH_ReadADS1230Data(&read_zero_data, &read_calib_factor);
    if (status != FLASH_OK)
    {
        printf("读取失败！错误码: %d\n", status);
        return status;
    }
    printf("成功\n");
    
    // 验证数据
    printf("验证数据:\n");
    printf("  写入零位数据: 0x%08X\n", write_zero_data);
    printf("  读取零位数据: 0x%08X\n", read_zero_data);
    printf("  写入校准因子: %.6f\n", write_calib_factor);
    printf("  读取校准因子: %.6f\n", read_calib_factor);
    
    if ((read_zero_data == write_zero_data) && 
        (read_calib_factor == write_calib_factor))
    {
        printf("\n=== 测试成功！数据读写验证通过 ===\n");
        return FLASH_OK;
    }
    else
    {
        printf("\n=== 测试失败！数据不匹配 ===\n");
        return FLASH_ERROR;
    }
}

/**
 * @brief 主函数示例
 * @note 实际应用中，此代码需要集成到完整的系统中
 *       系统初始化通常由CubeMX生成
 */
int main(void)
{
    // 系统初始化代码（通常由CubeMX生成）
    // 这里应该包含：
    // - 系统时钟初始化
    // - 外设初始化
    // - 中断配置等
    
    // 调用FLASH测试
    FLASH_Test();
    
    // 运行ADS1230数据测试
    ADS1230_FlashTest();
    
    while (1)
    {
        // 主循环
        // 实际应用中可以在这里执行其他任务
        
        // 简单的LED闪烁或延时（如果需要）
        // ...
    }
}